package com.inibb.app.sftp.impl.jsch;

import java.io.File;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;



import com.inibb.app.sftp.RemoteFileEntry;
import com.inibb.app.sftp.SFTPAuthInfo;
import com.inibb.app.sftp.SFTPConnection;
import com.inibb.app.sftp.SFTPConnectionPool;
import com.inibb.app.sftp.exception.SFTPException;
import com.inibb.app.sftp.exception.SFTPIOException;
import com.inibb.app.sftp.exception.SFTPLocalIOException;
import com.inibb.app.sftp.exception.SFTPRemoteFileNotFoundException;
import com.inibb.app.sftp.exception.SFTPRemoteIOException;
import com.inibb.app.sftp.exception.SFTPRemotePermissionDeniedException;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;
import com.jcraft.jsch.ChannelSftp.LsEntry;

/**
 * <p>Descriition: Implements SFTPConnection interface, include all sftp motheds </p>
 * <p>Created by Nick.HT.Chu </p>
 * <p>Create Date 2006-6-16 14:24  </P>
 */

public class JschSFTPConnection implements SFTPConnection {
	
	private static final char FS = '/';
	private Session session ;
	private ChannelSftp cSftp;
	//private static JschSFTPConnection jschSFtpCon;
	private static final JSch jsch = new JSch();
	private static final Logger LOG = LoggerFactory.getLogger(JschSFTPConnection.class);

	private Hashtable config = null;
	private boolean noneCipherMode = false;
	private int connectionTimeout = 30000;
	
	private static Hashtable CONFIG_NONE_CIPHER = new Hashtable();
	private static Hashtable CONFIG_NORMAL_CIPHER = new Hashtable();
	
	static {
//		CONFIG_NONE_CIPHER.put("cipher.s2c", "none,blowfish-cbc,3des-cbc");
//		CONFIG_NONE_CIPHER.put("cipher.c2s", "none,blowfish-cbc,3des-cbc");
//		
//		CONFIG_NORMAL_CIPHER.put("cipher.s2c", "blowfish-cbc,3des-cbc");
//		CONFIG_NORMAL_CIPHER.put("cipher.c2s", "blowfish-cbc,3des-cbc");
		

//		CONFIG_NONE_CIPHER.put("cipher.s2c", "none,des-cbc,3des-cbc,blowfish-cbc");
//		CONFIG_NONE_CIPHER.put("cipher.c2s", "none,des-cbc,3des-cbc,blowfish-cbc");
//
//		CONFIG_NORMAL_CIPHER.put("cipher.s2c", "des-cbc,3des-cbc,blowfish-cbc");
//		CONFIG_NORMAL_CIPHER.put("cipher.c2s", "des-cbc,3des-cbc,blowfish-cbc");

		CONFIG_NONE_CIPHER.put("cipher.s2c", "none,aes128-cbc,3des-cbc,blowfish-cbc");
		CONFIG_NONE_CIPHER.put("cipher.c2s", "none,aes128-cbc,3des-cbc,blowfish-cbc");

		CONFIG_NORMAL_CIPHER.put("cipher.s2c", "aes128-cbc,3des-cbc,blowfish-cbc");
		CONFIG_NORMAL_CIPHER.put("cipher.c2s", "aes128-cbc,3des-cbc,blowfish-cbc");
		
	}
	
	public JschSFTPConnection(){
		
		//config = new Hashtable();
		//config.put("cipher.s2c", "none,3des-cbc,blowfish-cbc");
		//config.put("cipher.c2s", "none,3des-cbc,blowfish-cbc");
		
	}
	
	
//	public static synchronized JschSFTPConnection getInstance(){
//		if(jschSFtpCon==null){
//			jschSFtpCon = new JschSFTPConnection();
//		}
//		return jschSFtpCon;
//	}
	/**
	 * Make a SFTP connection to the target host and port with the given authentication info.
	 * @param addr - address of the target SFTP server
	 * @param port - port number of the target SFTP server
	 * @param auth - SFTPAuthInfo holding the credential for logging in the target SFTP server
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public synchronized void connect(InetAddress addr, int port, SFTPAuthInfo auth)
		throws SFTPIOException, SFTPException 
	{
		try {
			disconnect();
		} catch (Exception e) {
			LOG.warn("Error on closing previous connection:"+e);
		}
		
		String userName = auth.getUsername();
		String passphrase = null;
		char[] pwd = auth.getPassphrase();
		if (pwd!=null) passphrase = new String(pwd);
		else pwd = new char[0];
		String host = addr.getHostAddress();
		
		try {
			session = jsch.getSession(userName,host,port);
			if (config!=null) {
				session.setConfig(config);
			}
			//session.setConfig(CONFIG_NORMAL_CIPHER);
			
			SSHUserInfo myUserInfo =new SSHUserInfo(auth);
			if (auth.getSshKeyFile()!=null) {
				String filePath= auth.getSshKeyFile().getAbsolutePath();
				jsch.addIdentity(filePath,passphrase);
			} 
			session.setUserInfo(myUserInfo);
			
			LOG.debug("Connecting to "+auth.getUsername()+"@"+addr.getHostAddress()+":"+port);
			session.connect(connectionTimeout);
			if (noneCipherMode) {
				session.setConfig(CONFIG_NONE_CIPHER);
				try {
					session.rekey();
				} catch (Exception e) {
					throw new SFTPIOException(SFTPException.CODE_RUNTIME,"Error when refreshing connection config.",e);
				}
			}
			
			LOG.debug("Establishing SFTP channel");
			Channel channel = session.openChannel("sftp");
			channel.connect();
			cSftp=(ChannelSftp)channel;
			
		} catch (JSchException e) {
			//Sys.log.printError(" get a sftp connection failure!!");
			throw new SFTPIOException(SFTPException.CODE_RUNTIME,"Fail to connect SFTP to "+userName+"@"+host+":"+port,e);
			
		}
	}
	/**
	 * Make a SFTP connection to the target host using DEFAULT_SSH_PORT with the given authentication info.
	 * @param addr - address of the target SFTP server
	 * @param auth - SFTPAuthInfo holding the credential for logging in the target SFTP server
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void connect(InetAddress addr, SFTPAuthInfo auth)
			throws SFTPIOException, SFTPException {
		    connect(addr,DEFAULT_SSH_PORT,auth);
	}
	/**
	 * Disconnect the SFTP connection
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void disconnect() throws SFTPIOException, SFTPException {
		//if(cSftp!=null&&cSftp.isClosed()){
		//if(cSftp!=null){
		//	cSftp.disconnect();
		//	cSftp.quit();
		//	cSftp=null;
		//}
		//Sys.log.printDebug("Disconnect ....");
		if(session!=null){
			synchronized (this) 
			{
				session.disconnect();
			}
			LOG.debug("Disconnected.");
			session =null;
			cSftp=null;
		}
	}
	/**
	 * Retrieve the directory listing of given path
	 * @param path - the <code>RemoteFileEntry</code> point to the directory / file you want to list, use <code>null</code> for current directort.
	 * @return The the <code>List</code> holding the list of <code>RemoteFileEntry</code>.
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public List list(RemoteFileEntry path) 
		throws SFTPRemoteFileNotFoundException, SFTPRemoteIOException, SFTPIOException, SFTPException 
	{
		if(cSftp!=null&&cSftp.isConnected()){
			ArrayList listV= new ArrayList();
			String realPath = null;
			try {
				if (path==null) realPath = cSftp.pwd();
				else {
					String _tmpPath = path.getRemoteFile();
					if (_tmpPath.charAt(0) == FS) {
						realPath = _tmpPath;
					} else {
						realPath = cSftp.pwd() + FS + _tmpPath;
					}
				}
				Vector jschVector;
				synchronized (this) {
					jschVector = cSftp.ls(realPath);
				}
				if (jschVector!=null){
					//File realPathFile = new File(realPath);
					String realPathParent = new File(realPath).getParent();
					boolean isCurrDir = false;
					boolean isCurrWildcard = isWildcard(realPath);
					Iterator it = jschVector.iterator();
					while (it.hasNext()) {
						LsEntry element = (LsEntry) it.next();
						if(".".equals(element.getFilename())||"..".equals(element.getFilename())){
							isCurrDir = true;
							continue;
						}
						RemoteFileEntry remoteFileEntry ;
						if (isCurrDir && !isCurrWildcard) {
							remoteFileEntry = new RemoteFileEntry(realPath+FS+element.getFilename());
						} else {
							remoteFileEntry = new RemoteFileEntry(realPathParent+FS+element.getFilename());
						}
						remoteFileEntry.setDir(element.getAttrs().isDir());
						remoteFileEntry.setLink(element.getAttrs().isLink());
						remoteFileEntry.setFileSize(element.getAttrs().getSize());
						remoteFileEntry.setLastModified((long)element.getAttrs().getMTime()*1000l);
						listV.add(remoteFileEntry);
						//System.out.println("getMTime="+element.getAttrs().getMTime());
						//System.out.println("getATime="+element.getAttrs().getATime());
					}
					path.setDir(isCurrDir);
				}
				return listV;
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+path);
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+path);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when getting list "+path);					
				} else throw new SFTPIOException(SFTPException.CODE_RUNTIME,"Error when getting list "+realPath,e);
			}
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}
	}
	
	private boolean isWildcard(String f) {
		return f.indexOf('*') >=0 || f.indexOf('?') >= 0 ;
	}
	
	/**
	 * Change the remote directory to the given path.
	 * @param path - the targer remote directory in <code>String</code>
	 * @return the current remote directory
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public RemoteFileEntry changeDir(String path) throws SFTPRemoteIOException,
			SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
			    try {
					synchronized (this) {
						cSftp.cd(path);
					}
				} catch (SftpException e) {
					if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
						throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+path);
					} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
						throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+path);					
					} else throw new SFTPIOException(SFTPIOException.CODE_RUNTIME,"Error when changing dir to "+path,e);
				}
				return new RemoteFileEntry(path);
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}
	}
	/**
	 * Change the remote directory to the given path.
	 * @param path - the targer remote directory in <code>RemoteFileEntry</code>
	 * @return the current remote directory
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public RemoteFileEntry changeDir(RemoteFileEntry path)
			throws SFTPRemoteIOException, SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
		    try {
				synchronized (this) {
					cSftp.cd(path.getRemoteFile());
				}
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+path);
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+path);					
				} else throw new SFTPIOException(SFTPIOException.CODE_RUNTIME,"Error when changing dir to "+path,e);
			}
			return path;
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}
	}
	/**
	 * Get the remote current directory
	 * @return <code>RemoteFileEntry</code> of remote current directory.
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 * @throws SftpException 
	 */
	public RemoteFileEntry pwd() 
		throws SFTPRemoteIOException, SFTPIOException, SFTPException 
	{
		if(cSftp!=null&&cSftp.isConnected()){
			String pwd;
			try {
				pwd = cSftp.pwd();
				if (pwd==null) return null;
				else return new RemoteFileEntry(pwd);
			} catch (SftpException e) {
				throw new SFTPException(SFTPException.CODE_RUNTIME, "Error in getting password", e);
			}

		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}
	}
	/**
	 * Remove the remote file.
	 * @param file - the <code>RemoteFileEntry</code> pointing to the remote file to be deleted.
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void remove(RemoteFileEntry file) throws SFTPRemoteIOException,
			SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
			try {
				synchronized (this) {
					cSftp.rm(file.getRemoteFile());
				}
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+file);
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+file);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when removing file "+file);					
				} else throw new SFTPIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when removing file "+file,e);
			}
			
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}

	}
	/**
	 * Remove the remote directory.
	 * @param file - the <code>RemoteFileEntry</code> pointing to the remote directory to be deleted.
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void removeDir(RemoteFileEntry dir) throws SFTPRemoteIOException,
			SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
			try {
				synchronized (this) {
					cSftp.rmdir(dir.getRemoteFile());
				}
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+dir);
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+dir);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when removing dir "+dir);					
				} else throw new SFTPIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when removing dir "+dir,e);
			}
			
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}
	}
	/**
	 * Rename or Move the remote file or directory
	 * @param source - the original remote file / directory to be renamed / moved.
	 * @param target - the target remote file / directory 
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void rename(RemoteFileEntry source, RemoteFileEntry target)
			throws SFTPRemoteIOException, SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
			
			try {
				synchronized (this) {
					cSftp.rename(source.getRemoteFile(),target.getRemoteFile());
				}
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+source);
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+source+"->"+target);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when renaming file "+source+"->"+target);					
				} else throw new SFTPIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when renaming file "+source+"->"+target,e);

			}
			
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}

	}
	/**
	 * Create a remote directory
	 * @param dir - the directory to be created
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void mkdir(RemoteFileEntry dir) throws SFTPRemoteIOException,
			SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
			try {
				synchronized (this) {
					cSftp.mkdir(dir.getRemoteFile());
				}
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemoteIOException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Permission denied."+dir);					
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+dir);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when making dir "+dir);					
				} else throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when making dir "+dir,e);
			}
			
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}

	}
	/**
	 * Put a local file to remote destination
	 * @param source - the file to be put
	 * @param dest - the remote target destination of the file 
	 * @throws SFTPLocalIOException - When I/O related exception occured in local side
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network or I/O related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void put(File source, RemoteFileEntry dest)
		throws SFTPRemoteIOException, SFTPLocalIOException, SFTPIOException, SFTPException
	{
		if (!source.canRead()) {
			throw new SFTPLocalIOException(SFTPLocalIOException.CODE_RUNTIME,"File not found: "+source);
		}
		if(cSftp!=null&&cSftp.isConnected()){
			
			try {			
				synchronized (this) {
					cSftp.put(source.getAbsolutePath(),dest.getRemoteFile());
				}
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote path not found."+dest.getParent());
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemoteIOException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Permission denied."+dest);					
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+dest);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when putting file "+dest);					
				} else throw new SFTPIOException(SFTPIOException.CODE_RUNTIME,"Error when putting file "+dest,e);
			}
			
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}


	}
	/**
	 * Get a remote file
	 * @param source - the remote source file to be retrieved
	 * @param dest - the local target destination of the file.
	 * @throws SFTPLocalIOException - When I/O related exception occured in local side
	 * @throws SFTPRemoteIOException - When I/O related exception occured in remote side
	 * @throws SFTPIOException - When network or I/O related exception occurs
	 * @throws SFTPException - When SFTP related exception occurs
	 */
	public void get(RemoteFileEntry source, File dest)
			throws SFTPRemoteIOException, SFTPLocalIOException, SFTPIOException, SFTPException {
		if(cSftp!=null&&cSftp.isConnected()){
			File p = dest.getParentFile();
			if (p!=null && !p.isDirectory()) {
				throw new SFTPLocalIOException(SFTPLocalIOException.CODE_RUNTIME,"Path "+p+" does not exists.");
			}
			
			try {
				synchronized (this) {
					cSftp.get(source.getRemoteFile(), dest.getAbsolutePath());
				}
				//LOG.debug(" get file  "+source+"  var sftp success!!");
			} catch (SftpException e) {
				if (e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE) {
					throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"Remote file not found."+source);
				} else if (e.id == ChannelSftp.SSH_FX_PERMISSION_DENIED) {
					throw new SFTPRemotePermissionDeniedException(SFTPRemotePermissionDeniedException.CODE_RUNTIME,"Permission denied."+source);					
				} else if (e.id == ChannelSftp.SSH_FX_FAILURE) {
					throw new SFTPRemoteIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when getting file "+source);					
				} else throw new SFTPIOException(SFTPRemoteIOException.CODE_RUNTIME,"Error when getting file "+source,e);
			//} catch (FileNotFoundException e) {
			//	throw new SFTPRemoteFileNotFoundException(SFTPRemoteFileNotFoundException.CODE_RUNTIME,"remote file not fund",e);
			}
			
		}else{
			//Sys.log.printError(" sftp connection is closed or null !!");
			throw new SFTPIOException (SFTPException.CODE_RUNTIME,"SFTP connection not connected.");
		}

	}
	
	public void setConfig(Hashtable config) {
		this.config = config;
	}
	
	/**
	 * Return the connection status.
	 * @return
	 */
	public boolean isConnected() {
		if (session!=null) return session.isConnected();
		else return false;
	}


	/*
	 * @see com.pccw.oframework.sftp.SFTPConnection#setNoneCipherMode(boolean)
	 */
	public void setNoneCipherMode(boolean b) {
		noneCipherMode = b;
	}
	
	protected void finalize() {
		if(session!=null){
			session.disconnect();
		}
	}
	
}
